﻿package com.fly.create;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.Observable;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Pattern;

public class TextUtil extends Observable
{
    private static TextUtil instance = new TextUtil();
    
    // 源文件目录，一般为工程路径
    private String sourceDir;
    
    // 目标文件目录
    private String targetDir;
    
    private static String WebRootName = "/WebRoot/";
    
    private Set<String> normalClassPath = new TreeSet<String>();
    
    // 内部类
    private Set<String> innerClassPath = new TreeSet<String>();
    
    public static TextUtil getInstance()
    {
        return instance;
    }
    
    // init
    public void init()
    {
        normalClassPath.clear();
        innerClassPath.clear();
    }
    
    // 过滤补丁文件
    public void filter(String text)
    {
        text = text.replace("\\", "/");
        
        // 删除：Deleted --中英文版本下刪除操作,匹配 任意非换行字符 .不区分大小写a-z字符
        if (text == null || text.trim().length() == 0 || text.contains("删除") || text.contains("Deleted") || !Pattern.matches(".+\\.(?i)[a-z]+", text))
        {
            return;
        }
        // java与class文件对应关系
        if (text.contains("/src/"))
        {
            // . 匹配除 "\n" 之外的任何单个字符。
            // \S 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。
            // \. 匹配 "."
            normalClassPath.add(text.replaceAll(".+/src/", WebRootName + "WEB-INF/classes/").replace(".java", ".class").trim());
            return;
        }
        if (text.contains("/WebRoot/"))
        {
            normalClassPath.add(text.replaceAll(".+/WebRoot/", "/WebRoot/").trim());
        }
        if (text.contains("/WebContent/"))
        {
            normalClassPath.add(text.replaceAll(".+/WebContent/", "/WebRoot/").trim());
        }
    }
    
    // 创建文件
    public void process()
    {
        setChanged();
        notifyObservers(DateUtil.getCurrDateTimeStr() + ": 开始创建补丁文件！");
        if (normalClassPath.isEmpty())
        {
            setChanged();
            notifyObservers(DateUtil.getCurrDateTimeStr() + ": 未创建任何补丁文件！");
            return;
        }
        
        // 处理web工程名为 WebContent
        if (new File(sourceDir + "/WebContent/").exists())
        {
            WebRootName = "/WebContent/";
        }
        
        for (String text : normalClassPath)
        {
            copyFile(text.replace("/WebRoot/", WebRootName));
        }
        createReadMeFile();
        setChanged();
        notifyObservers(DateUtil.getCurrDateTimeStr() + ": 补丁文件创建结束！\n--------------------------------------------------------------------------------------------- ");
        
    }
    
    // 创建说明文件
    public void createReadMeFile()
    {
        if (normalClassPath.isEmpty())
        {
            return;
        }
        OutputStream fos = null;
        BufferedWriter writer = null;
        try
        {
            String fileName = new StringBuilder(targetDir).append("说明").append(".txt").toString();
            setChanged();
            notifyObservers(DateUtil.getCurrDateTimeStr() + ": 创建 " + fileName);
            
            File file = new File(fileName);
            // false: not append
            fos = new FileOutputStream(file, false);
            writer = new BufferedWriter(new OutputStreamWriter(fos, "ISO-8859-1"));
            
            writer.write("Created Time: " + DateUtil.getCurrDateTimeStr());
            writer.newLine();
            
            writer.write("Files Number: " + (normalClassPath.size() + innerClassPath.size()));
            writer.newLine();
            
            for (String text : normalClassPath)
            {
                writer.write(text.replace("/WebRoot/", "/"));
                writer.newLine();
            }
            for (String t : innerClassPath)
            {
                writer.write(t);
                writer.newLine();
            }
            writer.newLine();
        }
        catch (Exception e)
        {
        }
        finally
        {
            try
            {
                if (writer != null)
                {
                    writer.close();
                }
            }
            catch (IOException e)
            {
            }
            try
            {
                if (fos != null)
                {
                    fos.close();
                }
            }
            catch (IOException e)
            {
            }
        }
    }
    
    /**
     * @param relativePath 相对路径
     */
    private void copyFile(String relativePath)
    {
        copyFile(sourceDir + relativePath, targetDir + relativePath.replace(WebRootName, "/"));
        if (relativePath.endsWith(".class"))
        {
            File srcfile = new File(sourceDir + relativePath);
            File[] files = srcfile.getParentFile().listFiles();
            
            // 构造有内部类的 Pattern
            Pattern pattern = Pattern.compile(srcfile.getName().replace(".", "\\$\\S+."));
            for (File file : files)
            {
                // 处理内部类java文件的class
                if (file.isFile() && pattern.matcher(file.getName()).find())
                {
                    String path = file.getAbsolutePath().replace("\\", "/");
                    String relPath = path.replaceAll(".*" + WebRootName, "/");
                    copyFile(path, targetDir + relPath);
                    innerClassPath.add(relPath);
                }
            }
        }
    }
    
    /**
     * 
     * @param sourcePath
     * @param targetPath
     */
    private void copyFile(String sourcePath, String targetPath)
    {
        File source = new File(sourcePath);
        File target = new File(targetPath);
        if (!source.exists())
        {
            setChanged();
            StringBuilder sb = new StringBuilder("读取文件失败， ").append(source.getAbsolutePath());
            notifyObservers(sb.toString());
            return;
        }
        
        if (!target.exists())
        {
            target.getParentFile().mkdirs();
        }
        
        FileInputStream in = null;
        FileOutputStream out = null;
        String filePathName = target.getAbsolutePath();
        try
        {
            in = new FileInputStream(source);
            out = new FileOutputStream(target);
            // 8K 缓存
            byte[] buffer = new byte[8192];
            int ins = in.read(buffer);
            while (ins != -1)
            {
                out.write(buffer, 0, ins);
                ins = in.read(buffer);
            }
            out.flush();
        }
        catch (FileNotFoundException e)
        {
            setChanged();
            StringBuilder sb = new StringBuilder("创建 [ ").append(filePathName).append(" ]失败，").append(e.getMessage());
            notifyObservers(sb.toString());
        }
        catch (IOException e)
        {
            setChanged();
            StringBuilder sb = new StringBuilder("创建 [ ").append(filePathName).append(" ]失败，").append(e.getMessage());
            notifyObservers(sb.toString());
        }
        finally
        {
            try
            {
                if (in != null)
                {
                    in.close();
                }
            }
            catch (IOException e)
            {
                setChanged();
                StringBuilder sb = new StringBuilder("创建 [ ").append(filePathName).append(" ]失败，").append(e.getMessage());
                notifyObservers(sb.toString());
            }
            try
            {
                if (out != null)
                {
                    out.close();
                }
                setChanged();
                StringBuilder sb = new StringBuilder("****创建成功**** , ").append(filePathName);
                notifyObservers(sb.toString());
            }
            catch (IOException e)
            {
                setChanged();
                StringBuilder sb = new StringBuilder("创建 [ ").append(filePathName).append(" ]失败，").append(e.getMessage());
                notifyObservers(sb.toString());
            }
        }
    }
    
    /**
     * 删除文件以及目录
     * 
     * @param filepath
     */
    public void delAll(String filepath)
    {
        File f = new File(filepath);
        // 判断是文件还是目录
        if (f.exists() && f.isDirectory())
        {
            for (File file : f.listFiles())
            {
                // 递归调用del方法并取得子目录路径
                if (file.isDirectory())
                {
                    delAll(file.getAbsolutePath());
                }
                // 删除文件
                file.delete();
            }
        }
    }
    
    /**
     * 删除说明文件<BR>
     * e.g. 说明.txt,说明001.txt...
     * 
     * @param filepath
     */
    public void delReadMe(String filepath)
    {
        File f = new File(filepath);
        // 判断是文件还是目录
        if (f.exists() && f.isDirectory())
        {
            for (File file : f.listFiles())
            {
                if (file.isFile() && file.getName().contains("说明") && file.getName().endsWith(".txt"))
                {
                    // 删除文件
                    file.delete();
                }
            }
        }
    }
    
    public String getSourceDir()
    {
        return sourceDir;
    }
    
    public void setSourceDir(String sourceDir)
    {
        this.sourceDir = sourceDir;
    }
    
    public String getTargetDir()
    {
        return targetDir;
    }
    
    public void setTargetDir(String targetDir)
    {
        this.targetDir = targetDir;
    }
    
    public Set<String> getTextSet()
    {
        return normalClassPath;
    }
    
}
